home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / 3d / OglBench.lha / OglBench / Storm-Project / oglbench.c next >
C/C++ Source or Header  |  1999-01-03  |  33KB  |  1,279 lines

  1. /* oglbench.c -- An OpenGL benchmarking program.
  2.  * Code is derived from dinoshade.c by Mark J. Kilgard,
  3.  * and isosurf.c by Brian Paul.  Combined by Patrick H. Madden,
  4.  * phm@ikm.com
  5.  *
  6.  * This program reads in the file isosurf.dat to obtain a list
  7.  * of triangles for a rendered surface.  To run as a benchmark,
  8.  * press a lowercase b; output is sent to standard out, so you'll
  9.  * probably want to redirect it to a file.
  10.  *
  11.  * Comment block below is from Mark J. Kilgard's dinoshade....
  12.  */
  13.  
  14. /* Copyright (c) Mark J. Kilgard, 1994, 1997.  */
  15.  
  16. /* This program is freely distributable without licensing fees 
  17.    and is provided without guarantee or warrantee expressed or 
  18.    implied. This program is -not- in the public domain. */
  19.  
  20. /* Example for PC game developers to show how to *combine* texturing,
  21.    reflections, and projected shadows all in real-time with OpenGL.
  22.    Robust reflections use stenciling.  Robust projected shadows
  23.    use both stenciling and polygon offset.  PC game programmers
  24.    should realize that neither stenciling nor polygon offset are 
  25.    supported by Direct3D, so these real-time rendering algorithms
  26.    are only really viable with OpenGL. 
  27.    
  28.    The program has modes for disabling the stenciling and polygon
  29.    offset uses.  It is worth running this example with these features
  30.    toggled off so you can see the sort of artifacts that result.
  31.    
  32.    Notice that the floor texturing, reflections, and shadowing
  33.    all co-exist properly. */
  34.  
  35. /* When you run this program:  Left mouse button controls the
  36.    view.  Middle mouse button controls light position (left &
  37.    right rotates light around dino; up & down moves light
  38.    position up and down).  Right mouse button pops up menu. */
  39.  
  40. /* Check out the comments in the "redraw" routine to see how the
  41.    reflection blending and surface stenciling is done.  You can
  42.    also see in "redraw" how the projected shadows are rendered,
  43.    including the use of stenciling and polygon offset. */
  44.  
  45. /* This program is derived from glutdino.c */
  46.  
  47. /* Compile: cc -o oglbench oglbench.c -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */
  48.  
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include <math.h>       /* for cos(), sin(), and sqrt() */
  53. #include <GL/glut.h>    /* OpenGL Utility Toolkit header */
  54.  
  55. /* Some <math.h> files do not define M_PI... */
  56. #ifndef M_PI
  57. #define M_PI 3.14159265
  58. #endif
  59.  
  60. /* Variable controlling various rendering modes. */
  61. static int stencilReflection = 1, stencilShadow = 1, offsetShadow = 1;
  62. static int renderShadow = 1, renderDinosaur = 1, renderReflection = 1;
  63. static int linearFiltering = 0, useMipmaps = 0, useTexture = 1;
  64. static int reportSpeed = 0;
  65. static int animation = 0;
  66. static GLboolean lightSwitch = GL_TRUE;
  67. static int directionalLight = 1;
  68. static int forceExtension = 0;
  69. static int bench_iter = 10;
  70. static int object_type = 0;
  71. static int shade_type = 0;
  72.  
  73. /* Time varying or user-controled variables. */
  74. static float jump = 0.0;
  75. static float lightAngle = 50.0, lightHeight = 20;
  76. GLfloat angle = -180;   /* in degrees */
  77. GLfloat angle2 = 30;   /* in degrees */
  78.  
  79. int moving, startx, starty;
  80. int lightMoving = 0, lightStartX, lightStartY;
  81.  
  82. enum {
  83.   MISSING, EXTENSION, ONE_DOT_ONE
  84. };
  85. int polygonOffsetVersion;
  86.  
  87. static GLdouble bodyWidth = 3.0;
  88. /* *INDENT-OFF* */
  89. static GLfloat body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5},
  90.   {11, 11.5}, {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16},
  91.   {8, 16}, {7, 15}, {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2},
  92.   {1, 2} };
  93. static GLfloat arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9},
  94.   {15, 9.5}, {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10},
  95.   {13, 9}, {11, 11}, {9, 11} };
  96. static GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0},
  97.   {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} };
  98. static GLfloat eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15},
  99.   {9.6, 15.25}, {9, 15.25} };
  100. static GLfloat lightPosition[4];
  101. static GLfloat lightColor[] = {0.8, 1.0, 0.8, 1.0}; /* green-tinted */
  102. static GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0};
  103. /* *INDENT-ON* */
  104.  
  105. /* Nice floor texture tiling pattern. */
  106. static char *circles[] = {
  107.   "....xxxx........",
  108.   "..xxxxxxxx......",
  109.   ".xxxxxxxxxx.....",
  110.   ".xxx....xxx.....",
  111.   "xxx......xxx....",
  112.   "xxx......xxx....",
  113.   "xxx......xxx....",
  114.   "xxx......xxx....",
  115.   ".xxx....xxx.....",
  116.   ".xxxxxxxxxx.....",
  117.   "..xxxxxxxx......",
  118.   "....xxxx........",
  119.   "................",
  120.   "................",
  121.   "................",
  122.   "................",
  123. };
  124.  
  125.  
  126. static void
  127. makeFloorTexture(void)
  128. {
  129.   GLubyte floorTexture[16][16][3];
  130.   GLubyte *loc;
  131.   int s, t;
  132.  
  133.   /* Setup RGB image for the texture. */
  134.   loc = (GLubyte*) floorTexture;
  135.   for (t = 0; t < 16; t++) {
  136.     for (s = 0; s < 16; s++) {
  137.       if (circles[t][s] == 'x') {
  138.     /* Nice green. */
  139.         loc[0] = 0x1f;
  140.         loc[1] = 0x8f;
  141.         loc[2] = 0x1f;
  142.       } else {
  143.     /* Light gray. */
  144.         loc[0] = 0xaa;
  145.         loc[1] = 0xaa;
  146.         loc[2] = 0xaa;
  147.       }
  148.       loc += 3;
  149.     }
  150.   }
  151.  
  152.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  153.  
  154.   if (useMipmaps) {
  155.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  156.       GL_LINEAR_MIPMAP_LINEAR);
  157.     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 16, 16,
  158.       GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
  159.   } else {
  160.     if (linearFiltering) {
  161.       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  162.     } else {
  163.       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  164.     }
  165.     glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
  166.       GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
  167.   }
  168. }
  169.  
  170. enum {
  171.   X, Y, Z, W
  172. };
  173. enum {
  174.   A, B, C, D
  175. };
  176.  
  177. /* Create a matrix that will project the desired shadow. */
  178. void
  179. shadowMatrix(GLfloat shadowMat[4][4],
  180.   GLfloat groundplane[4],
  181.   GLfloat lightpos[4])
  182. {
  183.   GLfloat dot;
  184.  
  185.   /* Find dot product between light position vector and ground plane normal. */
  186.   dot = groundplane[X] * lightpos[X] +
  187.     groundplane[Y] * lightpos[Y] +
  188.     groundplane[Z] * lightpos[Z] +
  189.     groundplane[W] * lightpos[W];
  190.  
  191.   shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
  192.   shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
  193.   shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
  194.   shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
  195.  
  196.   shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
  197.   shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
  198.   shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
  199.   shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
  200.  
  201.   shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
  202.   shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
  203.   shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
  204.   shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
  205.  
  206.   shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
  207.   shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
  208.   shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
  209.   shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
  210.  
  211. }
  212.  
  213. /* Find the plane equation given 3 points. */
  214. void
  215. findPlane(GLfloat plane[4],
  216.   GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
  217. {
  218.   GLfloat vec0[3], vec1[3];
  219.  
  220.   /* Need 2 vectors to find cross product. */
  221.   vec0[X] = v1[X] - v0[X];
  222.   vec0[Y] = v1[Y] - v0[Y];
  223.   vec0[Z] = v1[Z] - v0[Z];
  224.  
  225.   vec1[X] = v2[X] - v0[X];
  226.   vec1[Y] = v2[Y] - v0[Y];
  227.   vec1[Z] = v2[Z] - v0[Z];
  228.  
  229.   /* find cross product to get A, B, and C of plane equation */
  230.   plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
  231.   plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
  232.   plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
  233.  
  234.   plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
  235. }
  236.  
  237. void
  238. extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
  239.   GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
  240. {
  241.   static GLUtriangulatorObj *tobj = NULL;
  242.   GLdouble vertex[3], dx, dy, len;
  243.   int i;
  244.   int count = dataSize / (2 * sizeof(GLfloat));
  245.  
  246.   if (tobj == NULL) {
  247.     tobj = gluNewTess();  /* create and initialize a GLU
  248.                              polygon * * tesselation object */
  249. // (void*) eingefügt für StormC                             
  250.     gluTessCallback(tobj, GLU_BEGIN, (void*) glBegin);
  251.     gluTessCallback(tobj, GLU_VERTEX, (void*) glVertex2fv);  /* semi-tricky */
  252.     gluTessCallback(tobj, GLU_END, (void*) glEnd);
  253.   }
  254.   glNewList(side, GL_COMPILE);
  255.   glShadeModel(GL_SMOOTH);  /* smooth minimizes seeing
  256.                                tessellation */
  257.   gluBeginPolygon(tobj);
  258.   for (i = 0; i < count; i++) {
  259.     vertex[0] = data[i][0];
  260.     vertex[1] = data[i][1];
  261.     vertex[2] = 0;
  262.     gluTessVertex(tobj, vertex, data[i]);
  263.   }
  264.   gluEndPolygon(tobj);
  265.   glEndList();
  266.   glNewList(edge, GL_COMPILE);
  267.   glShadeModel(GL_FLAT);  /* flat shade keeps angular hands
  268.                              from being "smoothed" */
  269.   glBegin(GL_QUAD_STRIP);
  270.   for (i = 0; i <= count; i++) {
  271.     /* mod function handles closing the edge */
  272.     glVertex3f(data[i % count][0], data[i % count][1], 0.0);
  273.     glVertex3f(data[i % count][0], data[i % count][1], thickness);
  274.     /* Calculate a unit normal by dividing by Euclidean
  275.        distance. We * could be lazy and use
  276.        glEnable(GL_NORMALIZE) so we could pass in * arbitrary
  277.        normals for a very slight performance hit. */
  278.     dx = data[(i + 1) % count][1] - data[i % count][1];
  279.     dy = data[i % count][0] - data[(i + 1) % count][0];
  280.     len = sqrt(dx * dx + dy * dy);
  281.     glNormal3f(dx / len, dy / len, 0.0);
  282.   }
  283.   glEnd();
  284.   glEndList();
  285.   glNewList(whole, GL_COMPILE);
  286.   glFrontFace(GL_CW);
  287.   glCallList(edge);
  288.   glNormal3f(0.0, 0.0, -1.0);  /* constant normal for side */
  289.   glCallList(side);
  290.   glPushMatrix();
  291.   glTranslatef(0.0, 0.0, thickness);
  292.   glFrontFace(GL_CCW);
  293.   glNormal3f(0.0, 0.0, 1.0);  /* opposite normal for other side */
  294.   glCallList(side);
  295.   glPopMatrix();
  296.   glEndList();
  297. }
  298.  
  299. /* Enumerants for refering to display lists. */
  300. typedef enum {
  301.   RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
  302.   LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, surf_tri,
  303.                                                                 surf_strip
  304. } displayLists;
  305.  
  306. static GLfloat stripColor[] = { 0.8, 0.9, 0.9, 1.0};
  307.  
  308. static void
  309. makeDinosaur(void)
  310. {
  311.   extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
  312.     BODY_SIDE, BODY_EDGE, BODY_WHOLE);
  313.   extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
  314.     ARM_SIDE, ARM_EDGE, ARM_WHOLE);
  315.   extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
  316.     LEG_SIDE, LEG_EDGE, LEG_WHOLE);
  317.   extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
  318.     EYE_SIDE, EYE_EDGE, EYE_WHOLE);
  319. }
  320.  
  321. static void
  322. drawDinosaur(void)
  323.  
  324. {
  325.   glPushMatrix();
  326.   /* Translate the dinosaur to be at (0,8,0). */
  327.   glTranslatef(-8, 0, -bodyWidth / 2);
  328.   glTranslatef(0.0, jump, 0.0);
  329.   if (lightSwitch)
  330.     glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
  331.   else
  332.     glColor4fv(skinColor);
  333.  
  334.   glCallList(BODY_WHOLE);
  335.   glTranslatef(0.0, 0.0, bodyWidth);
  336.   glCallList(ARM_WHOLE);
  337.   glCallList(LEG_WHOLE);
  338.   glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
  339.   glCallList(ARM_WHOLE);
  340.   glTranslatef(0.0, 0.0, -bodyWidth / 4);
  341.   glCallList(LEG_WHOLE);
  342.   glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
  343.   if (lightSwitch)
  344.     glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
  345.   else
  346.     glColor4fv(eyeColor);
  347.  
  348.   glCallList(EYE_WHOLE);
  349.   glPopMatrix();
  350. }
  351.  
  352. #define MAXVERTS 10000
  353.  
  354. static GLfloat verts[MAXVERTS][3];
  355. static GLfloat norms[MAXVERTS][3];
  356. int numverts;
  357. GLboolean use_vertex_arrays = GL_FALSE;
  358.  
  359. static void drawTristrips()
  360. {
  361.    GLuint i;
  362.  
  363. #ifdef GL_EXT_vertex_array
  364.    if (use_vertex_arrays) {
  365.       glDrawArraysEXT( GL_TRIANGLE_STRIP, 0, numverts );
  366.    }
  367.    else {
  368. #endif
  369.       glBegin( GL_TRIANGLE_STRIP );
  370.       for (i=0;i<numverts;i++) {
  371.          glNormal3fv( norms[i] );
  372.          glVertex3fv( verts[i] );
  373.       }
  374.       glEnd();
  375. #ifdef GL_EXT_vertex_array
  376.    }
  377. #endif
  378.  }
  379.  
  380.  
  381.  
  382. static void drawTriangles()
  383. {
  384.   int i;
  385.   
  386.   glBegin(GL_TRIANGLES);
  387.  
  388.   for (i = 0; i < numverts - 2; ++i)
  389.     {
  390.       glNormal3fv(norms[i]);
  391.       glVertex3fv(verts[i]);
  392.  
  393.       glNormal3fv(norms[i + 1]);
  394.       glVertex3fv(verts[i + 1]);
  395.  
  396.       glNormal3fv(norms[i + 2]);
  397.       glVertex3fv(verts[i + 2]);
  398.     }
  399.   glEnd();
  400. }
  401.  
  402. static void initTriangles(char *filename)
  403. {
  404.   FILE *f;
  405.   
  406.   f = fopen(filename,"r");
  407.   if (!f) {
  408.     printf("couldn't read %s\n", filename);
  409.     exit(1);
  410.   }
  411.   
  412.   numverts = 0;
  413.   while (!feof(f) && numverts<MAXVERTS) {
  414.     fscanf( f, "%f %f %f  %f %f %f",
  415.        &verts[numverts][0], &verts[numverts][1], &verts[numverts][2],
  416.        &norms[numverts][0], &norms[numverts][1], &norms[numverts][2] );
  417.  
  418.     /* Scale the iso model so that it occupies some space.... */
  419.     verts[numverts][0] =  verts[numverts][0] * 10;
  420.     verts[numverts][1] =  verts[numverts][1] * 10 + 10;
  421.     verts[numverts][2] =  verts[numverts][2] * 10;
  422.  
  423.     numverts++;
  424.   }
  425.   numverts--;
  426.   
  427.   printf("%d vertices, %d triangles\n", numverts, numverts-2);
  428.   fclose(f);
  429.  
  430. }
  431.  
  432. static void drawObject()
  433. {
  434.   switch (object_type)
  435.     {
  436.     case 0:
  437.       drawDinosaur();
  438.       break;
  439.     case 1:
  440.       if (shade_type)
  441.     glShadeModel(GL_FLAT);
  442.       else
  443.     glShadeModel(GL_SMOOTH);
  444.  
  445.       glDisable(GL_CULL_FACE);
  446.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, stripColor);
  447.       drawTriangles();
  448.       glEnable(GL_CULL_FACE);
  449.       break;
  450.     case 2:
  451.       if (shade_type)
  452.     glShadeModel(GL_FLAT);
  453.       else
  454.     glShadeModel(GL_SMOOTH);
  455.  
  456.       glDisable(GL_CULL_FACE);
  457.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, stripColor);
  458.       drawTristrips();
  459.       glEnable(GL_CULL_FACE);
  460.       break;
  461.     case 3:
  462.       if (shade_type)
  463.     glShadeModel(GL_FLAT);
  464.       else
  465.     glShadeModel(GL_SMOOTH);
  466.  
  467.       glDisable(GL_CULL_FACE);
  468.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, stripColor);
  469.       glCallList(surf_tri);
  470.       glEnable(GL_CULL_FACE);
  471.       break;
  472.     case 4:
  473.       if (shade_type)
  474.     glShadeModel(GL_FLAT);
  475.       else
  476.     glShadeModel(GL_SMOOTH);
  477.  
  478.       glDisable(GL_CULL_FACE);
  479.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, stripColor);
  480.       glCallList(surf_strip);
  481.       glEnable(GL_CULL_FACE);
  482.       break;
  483.     }
  484. }
  485.  
  486. static GLfloat floorVertices[4][3] = {
  487.   { -20.0, 0.0, 20.0 },
  488.   { 20.0, 0.0, 20.0 },
  489.   { 20.0, 0.0, -20.0 },
  490.   { -20.0, 0.0, -20.0 },
  491. };
  492.  
  493. /* Draw a floor (possibly textured). */
  494. static void
  495. drawFloor(void)
  496. {
  497.   glDisable(GL_LIGHTING);
  498.  
  499.   if (useTexture) {
  500.     glEnable(GL_TEXTURE_2D);
  501.   }
  502.  
  503.   glBegin(GL_QUADS);
  504.     glTexCoord2f(0.0, 0.0);
  505.     glVertex3fv(floorVertices[0]);
  506.     glTexCoord2f(0.0, 16.0);
  507.     glVertex3fv(floorVertices[1]);
  508.     glTexCoord2f(16.0, 16.0);
  509.     glVertex3fv(floorVertices[2]);
  510.     glTexCoord2f(16.0, 0.0);
  511.     glVertex3fv(floorVertices[3]);
  512.   glEnd();
  513.  
  514.   if (useTexture) {
  515.     glDisable(GL_TEXTURE_2D);
  516.   }
  517.  
  518.   if (lightSwitch)
  519.     glEnable(GL_LIGHTING);
  520. }
  521.  
  522. static GLfloat floorPlane[4];
  523. static GLfloat floorShadow[4][4];
  524.  
  525. static void
  526. redraw(void)
  527. {
  528.   int start, end;
  529.  
  530.   if (reportSpeed)
  531.     {
  532.       start = glutGet(GLUT_ELAPSED_TIME);
  533.     }
  534.  
  535.   if (lightSwitch) 
  536.     {
  537.       glEnable(GL_LIGHT0);
  538.       glEnable(GL_LIGHTING);
  539.     } 
  540.   else
  541.     {
  542.       glDisable(GL_LIGHT0);
  543.       glDisable(GL_LIGHTING);
  544.     }
  545.   
  546.   /* Clear; default stencil clears to zero. */
  547.   if ((stencilReflection && renderReflection) ||
  548.       (stencilShadow && renderShadow))
  549.     {
  550.       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
  551.           GL_STENCIL_BUFFER_BIT);
  552.     }
  553.   else
  554.     {
  555.       /* Avoid clearing stencil when not using it. */
  556.       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  557.     }
  558.   
  559.   /* Reposition the light source. */
  560.   lightPosition[0] = 12*cos(lightAngle);
  561.   lightPosition[1] = lightHeight;
  562.   lightPosition[2] = 12*sin(lightAngle);
  563.   if (directionalLight)
  564.     {
  565.       lightPosition[3] = 0.0;
  566.     }
  567.   else
  568.     {
  569.       lightPosition[3] = 1.0;
  570.     }
  571.   
  572.   shadowMatrix(floorShadow, floorPlane, lightPosition);
  573.   
  574.   glPushMatrix();
  575.   /* Perform scene rotations based on user mouse input. */
  576.   glRotatef(angle2, 1.0, 0.0, 0.0);
  577.   glRotatef(angle, 0.0, 1.0, 0.0);
  578.   
  579.   /* Tell GL new light source position. */
  580.   glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
  581.   
  582.   if (renderReflection)
  583.     {
  584.       if (stencilReflection)
  585.     {
  586.       /* We can eliminate the visual "artifact" of seeing the "flipped"
  587.          dinosaur underneath the floor by using stencil.  The idea is
  588.          draw the floor without color or depth update but so that 
  589.          a stencil value of one is where the floor will be.  Later when
  590.          rendering the dinosaur reflection, we will only update pixels
  591.          with a stencil value of 1 to make sure the reflection only
  592.          lives on the floor, not below the floor. */
  593.       
  594.       /* Don't update color or depth. */
  595.       glDisable(GL_DEPTH_TEST);
  596.       glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  597.       
  598.       /* Draw 1 into the stencil buffer. */
  599.       glEnable(GL_STENCIL_TEST);
  600.       glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
  601.       glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
  602.       
  603.       /* Now render floor; floor pixels just get their stencil set to 1. */
  604.       drawFloor();
  605.       
  606.       /* Re-enable update of color and depth. */ 
  607.       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  608.       glEnable(GL_DEPTH_TEST);
  609.       
  610.       /* Now, only render where stencil is set to 1. */
  611.       glStencilFunc(GL_EQUAL, 1, 0xffffffff);  /* draw if ==1 */
  612.       glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  613.     }
  614.       
  615.       glPushMatrix();
  616.       
  617.       /* The critical reflection step: Reflect dinosaur through the floor
  618.      (the Y=0 plane) to make a relection. */
  619.       glScalef(1.0, -1.0, 1.0);
  620.       
  621.       /* Reflect the light position. */
  622.       glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
  623.       
  624.       /* To avoid our normals getting reversed and hence botched lighting
  625.      on the reflection, turn on normalize.  */
  626.       glEnable(GL_NORMALIZE);
  627.       glCullFace(GL_FRONT);
  628.       
  629.       /* Draw the reflected dinosaur. */
  630.       drawObject();
  631.       
  632.       /* Disable noramlize again and re-enable back face culling. */
  633.       glDisable(GL_NORMALIZE);
  634.       glCullFace(GL_BACK);
  635.       
  636.       glPopMatrix();
  637.       
  638.       /* Switch back to the unreflected light position. */
  639.       glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
  640.       
  641.       if (stencilReflection) {
  642.         glDisable(GL_STENCIL_TEST);
  643.       }
  644.     }
  645.   
  646.   /* Back face culling will get used to only draw either the top or the
  647.      bottom floor.  This let's us get a floor with two distinct
  648.      appearances.  The top floor surface is reflective and kind of red.
  649.      The bottom floor surface is not reflective and blue. */
  650.   
  651.   /* Draw "bottom" of floor in blue. */
  652.   glFrontFace(GL_CW);  /* Switch face orientation. */
  653.   glColor4f(0.1, 0.1, 0.7, 1.0);
  654.   drawFloor();
  655.   glFrontFace(GL_CCW);
  656.   
  657.   if (renderShadow) 
  658.     {
  659.       if (stencilShadow)
  660.     {
  661.       /* Draw the floor with stencil value 3.  This helps us only 
  662.          draw the shadow once per floor pixel (and only on the
  663.          floor pixels). */
  664.       glEnable(GL_STENCIL_TEST);
  665.       glStencilFunc(GL_ALWAYS, 3, 0xffffffff);
  666.       glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  667.     }
  668.     }
  669.   
  670.   /* Draw "top" of floor.  Use blending to blend in reflection. */
  671.   glEnable(GL_BLEND);
  672.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  673.   glColor4f(0.7, 0.0, 0.0, 0.3);
  674.   glColor4f(1.0, 1.0, 1.0, 0.3);
  675.   drawFloor();
  676.   glDisable(GL_BLEND);
  677.   
  678.   if (renderDinosaur) 
  679.     {
  680.       /* Draw "actual" dinosaur, not its reflection. */
  681.       drawObject();
  682.     }
  683.   
  684.   if (renderShadow) 
  685.     {
  686.       
  687.       /* Render the projected shadow. */
  688.       
  689.       if (stencilShadow) 
  690.     {
  691.       
  692.       /* Now, only render where stencil is set above 2 (ie, 3 where
  693.          the top floor is).  Update stencil with 2 where the shadow
  694.          gets drawn so we don't redraw (and accidently reblend) the
  695.          shadow). */
  696.       glStencilFunc(GL_LESS, 2, 0xffffffff);  /* draw if ==1 */
  697.       glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
  698.     }
  699.       
  700.       /* To eliminate depth buffer artifacts, we use polygon offset
  701.      to raise the depth of the projected shadow slightly so
  702.      that it does not depth buffer alias with the floor. */
  703.       if (offsetShadow) 
  704.     {
  705.       switch (polygonOffsetVersion) 
  706.         {
  707.         case EXTENSION:
  708. #ifdef GL_EXT_polygon_offset
  709.           glEnable(GL_POLYGON_OFFSET_EXT);
  710.           break;
  711. #endif
  712. #ifdef GL_VERSION_1_1
  713.         case ONE_DOT_ONE:
  714.           glEnable(GL_POLYGON_OFFSET_FILL);
  715.           break;
  716. #endif
  717.         case MISSING:
  718.           /* Oh well. */
  719.           break;
  720.         }
  721.     }
  722.       
  723.       /* Render 50% black shadow color on top of whatever the
  724.          floor appareance is. */
  725.       glEnable(GL_BLEND);
  726.       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  727.       glDisable(GL_LIGHTING);  /* Force the 50% black. */
  728.       glColor4f(0.0, 0.0, 0.0, 0.5);
  729.       
  730.       glPushMatrix();
  731.       /* Project the shadow. */
  732.       glMultMatrixf((GLfloat *) floorShadow);
  733.       drawObject();
  734.       glPopMatrix();
  735.       
  736.       glDisable(GL_BLEND);
  737.  
  738.  
  739.       if (lightSwitch)
  740.     glEnable(GL_LIGHTING);
  741.       
  742.       if (offsetShadow) 
  743.     {
  744.       switch (polygonOffsetVersion) 
  745.         {
  746. #ifdef GL_EXT_polygon_offset
  747.         case EXTENSION:
  748.           glDisable(GL_POLYGON_OFFSET_EXT);
  749.           break;
  750. #endif
  751. #ifdef GL_VERSION_1_1
  752.         case ONE_DOT_ONE:
  753.           glDisable(GL_POLYGON_OFFSET_FILL);
  754.           break;
  755. #endif
  756.         case MISSING:
  757.           /* Oh well. */
  758.           break;
  759.         }
  760.     }
  761.       if (stencilShadow)
  762.     {
  763.       glDisable(GL_STENCIL_TEST);
  764.     }
  765.     }
  766.  
  767.   
  768.   if (lightSwitch)
  769.     {
  770.       glPushMatrix();
  771.       glDisable(GL_LIGHTING);
  772.       glColor3f(1.0, 1.0, 0.0);
  773.  
  774.       if (directionalLight)
  775.     {      
  776.       /* Draw an arrowhead. */
  777.       glDisable(GL_CULL_FACE);
  778.       glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);
  779.       glRotatef(lightAngle * -180.0 / M_PI, 0, 1, 0);
  780.       glRotatef(atan(lightHeight/12) * 180.0 / M_PI, 0, 0, 1);
  781.       glBegin(GL_TRIANGLE_FAN);
  782.       glVertex3f(0, 0, 0);
  783.       glVertex3f(2, 1, 1);
  784.       glVertex3f(2, -1, 1);
  785.       glVertex3f(2, -1, -1);
  786.       glVertex3f(2, 1, -1);
  787.       glVertex3f(2, 1, 1);
  788.       glEnd();
  789.       /* Draw a white line from light direction. */
  790.       glColor3f(1.0, 1.0, 1.0);
  791.       glBegin(GL_LINES);
  792.       glVertex3f(0, 0, 0);
  793.       glVertex3f(5, 0, 0);
  794.       glEnd();
  795.       glEnable(GL_CULL_FACE);
  796.     }
  797.       else
  798.     {
  799.       /* Draw a yellow ball at the light source. */
  800.       glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);
  801.       glutSolidSphere(1.0, 5, 5);
  802.     }
  803.       glPopMatrix();  /* From the lighting markers */
  804.     }
  805.   
  806.   glPopMatrix();
  807.   
  808.   if (reportSpeed)
  809.     {
  810.       glFinish();
  811.       end = glutGet(GLUT_ELAPSED_TIME);
  812.       printf("Speed %.3g frames/sec (%d ms)\n", 1000.0/(end-start), end-start);
  813.     }
  814.   
  815.   glutSwapBuffers();
  816. }
  817.  
  818. /* ARGSUSED2 */
  819. static void
  820. mouse(int button, int state, int x, int y)
  821. {
  822.   if (button == GLUT_LEFT_BUTTON) {
  823.     if (state == GLUT_DOWN) {
  824.       moving = 1;
  825.       startx = x;
  826.       starty = y;
  827.     }
  828.     if (state == GLUT_UP) {
  829.       moving = 0;
  830.     }
  831.   }
  832.   if (button == GLUT_MIDDLE_BUTTON) {
  833.     if (state == GLUT_DOWN) {
  834.       lightMoving = 1;
  835.       lightStartX = x;
  836.       lightStartY = y;
  837.     }
  838.     if (state == GLUT_UP) {
  839.       lightMoving = 0;
  840.     }
  841.   }
  842. }
  843.  
  844. /* ARGSUSED1 */
  845. static void
  846. motion(int x, int y)
  847. {
  848.   if (moving) {
  849.     angle = angle + (x - startx);
  850.     angle2 = angle2 + (y - starty);
  851.     startx = x;
  852.     starty = y;
  853.     glutPostRedisplay();
  854.   }
  855.   if (lightMoving) {
  856.     lightAngle += (x - lightStartX)/40.0;
  857.     lightHeight += (lightStartY - y)/20.0;
  858.     lightStartX = x;
  859.     lightStartY = y;
  860.     glutPostRedisplay();
  861.   }
  862. }
  863.  
  864. /* Advance time varying state when idle callback registered. */
  865. static void
  866. idle(void)
  867. {
  868.   static float time = 0.0;
  869.  
  870.   time = glutGet(GLUT_ELAPSED_TIME) / 500.0;
  871.  
  872.   jump = 4.0 * fabs(sin(time)*0.5);
  873.   if (!lightMoving) {
  874.     lightAngle += 0.03;
  875.   }
  876.   glutPostRedisplay();
  877. }
  878.  
  879. enum {
  880.   M_NONE, M_MOTION, M_LIGHT, M_TEXTURE, M_SHADOWS, M_REFLECTION, M_DINOSAUR,
  881.   M_STENCIL_REFLECTION, M_STENCIL_SHADOW, M_OFFSET_SHADOW,
  882.   M_POSITIONAL, M_DIRECTIONAL, M_PERFORMANCE
  883. };
  884.  
  885. static void
  886. controlLights(int value)
  887. {
  888.   switch (value) {
  889.   case M_NONE:
  890.     return;
  891.   case M_MOTION:
  892.     animation = 1 - animation;
  893.     if (animation) {
  894.       glutIdleFunc(idle);
  895.     } else {
  896.       glutIdleFunc(NULL);
  897.     }
  898.     break;
  899.   case M_LIGHT:
  900.     lightSwitch = !lightSwitch;
  901.     break;
  902.   case M_TEXTURE:
  903.     useTexture = !useTexture;
  904.     break;
  905.   case M_SHADOWS:
  906.     renderShadow = 1 - renderShadow;
  907.     break;
  908.   case M_REFLECTION:
  909.     renderReflection = 1 - renderReflection;
  910.     break;
  911.   case M_DINOSAUR:
  912.     renderDinosaur = 1 - renderDinosaur;
  913.     break;
  914.   case M_STENCIL_REFLECTION:
  915.     stencilReflection = 1 - stencilReflection;
  916.     break;
  917.   case M_STENCIL_SHADOW:
  918.     stencilShadow = 1 - stencilShadow;
  919.     break;
  920.   case M_OFFSET_SHADOW:
  921.     offsetShadow = 1 - offsetShadow;
  922.     break;
  923.   case M_POSITIONAL:
  924.     directionalLight = 0;
  925.     break;
  926.   case M_DIRECTIONAL:
  927.     directionalLight = 1;
  928.     break;
  929.   case M_PERFORMANCE:
  930.     reportSpeed = 1 - reportSpeed;
  931.     break;
  932.   }
  933.   glutPostRedisplay();
  934. }
  935.  
  936. /* When not visible, stop animating.  Restart when visible again. */
  937. static void 
  938. visible(int vis)
  939. {
  940.   if (vis == GLUT_VISIBLE) {
  941.     if (animation)
  942.       glutIdleFunc(idle);
  943.   } else {
  944.     if (!animation)
  945.       glutIdleFunc(NULL);
  946.   }
  947. }
  948.  
  949. static void benchmark(void)
  950. {
  951.   int i;
  952.   int start, end;
  953.   int light_type;
  954.   int shadow_type;
  955.  
  956.   reportSpeed = 0;
  957.  
  958.   printf("oglbench 1.0\n");
  959.   printf("Benchmark of OpenGL rendering in a variety of modes\n");
  960.   printf("Mode options are separated by colons, in the following order.\n");
  961.   printf("  Texture  [0 for off, 1 for on]\n");
  962.   printf("  Lighting [0 for off, 1 for direction, flat, 2 for dir smooth\n");
  963.   printf("            3 for position flat, 4 for position smooth]\n");
  964.   printf("  Shadows  [0 for off, 1 for on, 2 offset, 3 stencil,\n");
  965.   printf("            4 stencil and offset]\n");
  966.   printf("  Reflect  [0 off, 1 on]\n");
  967.   printf("  Object   [0 dinosaur, 1 triangles, 2 tri-strip, \n");
  968.   printf("            3 DL triangles, 4 DL tri-strip]\n");
  969.   printf("VENDOR: %s\n", glGetString(GL_VENDOR));
  970.   printf("RENDERER: %s\n", glGetString(GL_RENDERER));
  971.   printf("VERSION: %s\n", glGetString(GL_VERSION));
  972.   printf("EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));
  973.  
  974.   for (useTexture = 0; useTexture <= 1; ++useTexture)
  975.     {
  976.       for (light_type = 0; light_type <= 4; ++light_type)
  977.     {
  978.       switch (light_type)
  979.         {
  980.         case 0:
  981.           lightSwitch = 0;
  982.           break;
  983.         case 1:
  984.           lightSwitch = 1;
  985.           directionalLight = 0;
  986.           shade_type = 0;
  987.           break;
  988.         case 2:
  989.           lightSwitch = 1;
  990.           directionalLight = 0;
  991.           shade_type = 1;
  992.           break;
  993.         case 3:
  994.           lightSwitch = 1;
  995.           directionalLight = 1;
  996.           shade_type = 0;
  997.           break;
  998.         case 4:
  999.           lightSwitch = 1;
  1000.           directionalLight = 1;
  1001.           shade_type = 1;
  1002.           break;
  1003.         }
  1004.       for (shadow_type = 0; shadow_type <= 4; ++shadow_type)
  1005.         {
  1006.           switch (shadow_type)
  1007.         {
  1008.         case 0:
  1009.           renderShadow = 0;
  1010.           break;
  1011.         case 1:
  1012.           renderShadow = 1;
  1013.           stencilShadow = 0;
  1014.           offsetShadow = 0;
  1015.           break;
  1016.         case 2:
  1017.           renderShadow = 1;
  1018.           stencilShadow = 0;
  1019.           offsetShadow = 1;
  1020.         case 3:
  1021.           renderShadow = 1;
  1022.           stencilShadow = 1;
  1023.           offsetShadow = 0;
  1024.         case 4:
  1025.           renderShadow = 1;
  1026.           stencilShadow = 1;
  1027.           offsetShadow = 1;
  1028.           break;
  1029.         }
  1030.           for (renderReflection = 0; renderReflection <= 1;
  1031.            ++renderReflection)
  1032.         {
  1033.           for (object_type = 0; object_type <= 4; ++object_type)
  1034.             {
  1035.               printf("%d:%d:%d:%d:%d  ",
  1036.                  useTexture,
  1037.                  light_type,
  1038.                  shadow_type,
  1039.                  renderReflection,
  1040.                  object_type);
  1041.               
  1042.               start = glutGet(GLUT_ELAPSED_TIME);
  1043.               for (i = 0; i < bench_iter; ++i)
  1044.             redraw();
  1045.               end = glutGet(GLUT_ELAPSED_TIME);
  1046.               printf("Speed %8.3f frames/sec (%8.3f ms)\n",
  1047.                  (1000.0/(end-start))*(float) bench_iter,
  1048.                  (end-start)/(float) bench_iter);
  1049.             }
  1050.         }
  1051.         }
  1052.     }
  1053.     }
  1054. }
  1055.  
  1056.  
  1057. /* Press any key to redraw; good when motion stopped and
  1058.    performance reporting on. */
  1059. /* ARGSUSED */
  1060. static void
  1061. key(unsigned char c, int x, int y)
  1062. {
  1063.   if (c == 27) {
  1064.     exit(0);  /* IRIS GLism, Escape quits. */
  1065.   }
  1066.   if (c == 'o')
  1067.     {
  1068.       ++object_type;
  1069.       if (object_type == 5)
  1070.     object_type = 0;
  1071.  
  1072.       printf("Use object type %d\n", object_type);
  1073.     }
  1074.   if (c == 's')
  1075.     {
  1076.       shade_type = 1 - shade_type;
  1077.     }
  1078.   if (c == 't')
  1079.     {
  1080.       useTexture = 1 - useTexture;
  1081.     }
  1082.   if (c == 'l')
  1083.     {
  1084.       lightSwitch = 1 - lightSwitch;
  1085.     }
  1086.   if (c == 'd')
  1087.     {
  1088.       directionalLight = 1 - directionalLight;
  1089.     }
  1090.   if (c == 'b')
  1091.     {
  1092.       benchmark();
  1093.     }
  1094.   if (c == 'z')
  1095.     {
  1096.       angle = angle - 5;
  1097.     }
  1098.   if (c == 'x')
  1099.     {
  1100.       angle = angle + 5;
  1101.     }
  1102.   if (c == 'Z')
  1103.     {
  1104.       angle2 = angle2 - 5;
  1105.     }
  1106.   if (c == 'X')
  1107.     {
  1108.       angle2 = angle2 + 5;
  1109.     }
  1110.  
  1111.   glutPostRedisplay();
  1112. }
  1113.  
  1114. /* Press any key to redraw; good when motion stopped and
  1115.    performance reporting on. */
  1116. /* ARGSUSED */
  1117. static void
  1118. special(int k, int x, int y)
  1119. {
  1120.   glutPostRedisplay();
  1121. }
  1122.  
  1123. static int
  1124. supportsOneDotOne(void)
  1125. {
  1126.   const char *version;
  1127.   int major, minor;
  1128.  
  1129.   version = (char *) glGetString(GL_VERSION);
  1130.   if (sscanf(version, "%d.%d", &major, &minor) == 2)
  1131.     return major >= 1 && minor >= 1;
  1132.   return 0;            /* OpenGL version string malformed! */
  1133. }
  1134.  
  1135. int
  1136. main(int argc, char **argv)
  1137. {
  1138.   int i;
  1139.  
  1140.   glutInit(&argc, argv);
  1141.   initTriangles("isosurf.dat");
  1142.  
  1143.   for (i=1; i<argc; i++) 
  1144.     {
  1145.       if (!strcmp("-linear", argv[i]))
  1146.     {
  1147.       linearFiltering = 1;
  1148.     }
  1149.  
  1150.       if (!strcmp("-mipmap", argv[i])) 
  1151.     {
  1152.       useMipmaps = 1;
  1153.     } 
  1154.  
  1155.       if (!strcmp("-ext", argv[i])) 
  1156.     {
  1157.       forceExtension = 1;
  1158.     }
  1159.       
  1160.       if (!strcmp("-iter", argv[i]))
  1161.     {
  1162.       bench_iter = atoi(argv[i + 1]);
  1163.       ++i;
  1164.     }
  1165.     }
  1166.  
  1167.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | 
  1168.               GLUT_STENCIL | GLUT_MULTISAMPLE);
  1169.  
  1170. #if 0
  1171.   /* In GLUT 4.0, you'll be able to do this an be sure to
  1172.      get 2 bits of stencil if the machine has it for you. */
  1173.   glutInitDisplayString("samples stencil>=2 rgb double depth");
  1174. #endif
  1175.  
  1176.   glutCreateWindow("Shadowy Leapin' Lizards");
  1177.   glutReshapeWindow(640, 400);
  1178.  
  1179.   if (glutGet(GLUT_WINDOW_STENCIL_SIZE) <= 1) {
  1180.     printf("dinoshade: Sorry, I need at least 2 bits of stencil.\n");
  1181.     exit(1);
  1182.   }
  1183.  
  1184.   /* Register GLUT callbacks. */
  1185.   glutDisplayFunc(redraw);
  1186.   glutMouseFunc(mouse);
  1187.   glutMotionFunc(motion);
  1188.   glutVisibilityFunc(visible);
  1189.   glutKeyboardFunc(key);
  1190.   glutSpecialFunc(special);
  1191.  
  1192.   glutCreateMenu(controlLights);
  1193.  
  1194.   glutAddMenuEntry("Toggle motion", M_MOTION);
  1195.   glutAddMenuEntry("-----------------------", M_NONE);
  1196.   glutAddMenuEntry("Toggle light", M_LIGHT);
  1197.   glutAddMenuEntry("Toggle texture", M_TEXTURE);
  1198.   glutAddMenuEntry("Toggle shadows", M_SHADOWS);
  1199.   glutAddMenuEntry("Toggle reflection", M_REFLECTION);
  1200.   glutAddMenuEntry("Toggle dinosaur", M_DINOSAUR);
  1201.   glutAddMenuEntry("-----------------------", M_NONE);
  1202.   glutAddMenuEntry("Toggle reflection stenciling", M_STENCIL_REFLECTION);
  1203.   glutAddMenuEntry("Toggle shadow stenciling", M_STENCIL_SHADOW);
  1204.   glutAddMenuEntry("Toggle shadow offset", M_OFFSET_SHADOW);
  1205.   glutAddMenuEntry("----------------------", M_NONE);
  1206.   glutAddMenuEntry("Positional light", M_POSITIONAL);
  1207.   glutAddMenuEntry("Directional light", M_DIRECTIONAL);
  1208.   glutAddMenuEntry("-----------------------", M_NONE);
  1209.   glutAddMenuEntry("Toggle performance", M_PERFORMANCE);
  1210.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  1211.   makeDinosaur();
  1212.  
  1213. #ifdef GL_VERSION_1_1
  1214.   if (supportsOneDotOne() && !forceExtension) {
  1215.     polygonOffsetVersion = ONE_DOT_ONE;
  1216.     glPolygonOffset(-2.0, -1.0);
  1217.   } else
  1218. #endif
  1219.   {
  1220. #ifdef GL_EXT_polygon_offset
  1221.   /* check for the polygon offset extension */
  1222.   if (glutExtensionSupported("GL_EXT_polygon_offset")) {
  1223.     polygonOffsetVersion = EXTENSION;
  1224.     glPolygonOffsetEXT(-0.1, -0.002);
  1225.   } else 
  1226. #endif
  1227.     {
  1228.       polygonOffsetVersion = MISSING;
  1229.       printf("\ndinoshine: Missing polygon offset.\n");
  1230.       printf("           Expect shadow depth aliasing artifacts.\n\n");
  1231.     }
  1232.   }
  1233.  
  1234.   glEnable(GL_CULL_FACE);
  1235.   glEnable(GL_DEPTH_TEST);
  1236.   glDisable(GL_TEXTURE_2D);
  1237.   glLineWidth(3.0);
  1238.  
  1239.   glMatrixMode(GL_PROJECTION);
  1240.   gluPerspective( /* field of view in degree */ 40.0,
  1241.   /* aspect ratio */ 1.0,
  1242.     /* Z near */ 20.0, /* Z far */ 100.0);
  1243.   glMatrixMode(GL_MODELVIEW);
  1244.   gluLookAt(0.0, 8.0, 60.0,  /* eye is at (0,0,30) */
  1245.     0.0, 8.0, 0.0,      /* center is at (0,0,0) */
  1246.     0.0, 1.0, 0.);      /* up is in postivie Y direction */
  1247.  
  1248.   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  1249.   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
  1250.   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
  1251.   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
  1252.   glEnable(GL_LIGHT0);
  1253.   glEnable(GL_LIGHTING);
  1254.  
  1255.   makeFloorTexture();
  1256.  
  1257.   /* Setup floor plane for projected shadow calculations. */
  1258.   findPlane(floorPlane, floorVertices[1], floorVertices[2], floorVertices[3]);
  1259.  
  1260.  
  1261.  
  1262.   /* Now make the call lists for either strips or triangles */
  1263.   glNewList(surf_tri, GL_COMPILE);
  1264.   drawTriangles();
  1265.   glEndList();
  1266.  
  1267.   glNewList(surf_strip, GL_COMPILE);
  1268.   drawTristrips();
  1269.   glEndList();
  1270.  
  1271.  
  1272.   glutMainLoop();
  1273.  
  1274.  
  1275.  
  1276.  
  1277.   return 0;             /* ANSI C requires main to return int. */
  1278. }
  1279.